import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import CMD from './cmd';
import { ChargeCardService } from './modules/charge-card/charge-card.service';
import { ChargeService } from './modules/charge/charge.service';
import { ProfitSettlementService } from './modules/profit-settlement/profit-settlement.service';
import { MqttService } from './mqtt/mqtt.service';
import { RabbitmqService } from './rabbitmq/rabbitmq.service';
import { RedisService } from './redis/redis.service';

const cluster = require('cluster')

function getWorkNo() {
  if(process.env.instance_var != undefined) { //pm2模式
     return Number(process.env[process.env.instance_var])
  }else {
    return cluster.isPrimary ? 0 : process.env.workNo
  }
}

async function bootstrap() {
  const app = await NestFactory.createApplicationContext(AppModule);
  const configService = app.get(ConfigService)

  const workNo = getWorkNo()
  if(workNo == 0) {
    const chargeService = app.get(ChargeService)
    const redis = app.get(RedisService)

    const redisKeys = configService.get('redisKey.charge')

    const rabbitmq = app.get(RabbitmqService);
    await rabbitmq.connect()

    //开始充电、增加充电延时退款
    rabbitmq.consume(configService.get('rabbitmq.queue.dealLetterChargeResQueue'), msg => {
      console.log('充电延时消息')
      console.log(msg)
      const data = JSON.parse(msg)
      if(!data) return
      const type = data.type
      const orderId = data.orderId
      if(type == 1) { //充电
        redis.store.get(redisKeys.startCharge + orderId).then(status => {
          console.log('充电')
          console.log('当前状态', status)
          if(status == null) return
          if(status != '1' && status != '2') chargeService.startChargeRefund(orderId)
        })
      }else {
        redis.store.get(redisKeys.addCharge + orderId).then(status => {
          console.log('增加充电')
          console.log('当前状态', status)
          if(status == null) return
          if(status != '1' && status != '2') chargeService.addChargeRefund(orderId)
        })
      }
    })


    if(cluster.isPrimary) {
      for(let i = 1; i <= 4; i ++) {
        cluster.fork({workNo : i})
      }
    }


  }else {
    if(workNo == 1) { //监听开始充电，增加充电，停止充电返回结果
      const topic = configService.get('mqtt.topic.chargeRes')
      const chargeService = app.get(ChargeService)
      const mqtt = app.get(MqttService)
      await mqtt.connect()
      
      mqtt.message((topic, data) => {
        console.log('收到充电设备反馈结果')
        console.log(data)
        if(data.chargeAction == 0) { //开始充电
          chargeService.startChargeNotify(data.orderMsgId, data.result)
        }else if(data.chargeAction == 1) { //增加充电
          chargeService.addChargeNotify(data.orderMsgId, data.result)
        }else if(data.chargeAction == 2) { //停止充电
          chargeService.stopChargeNotify(data.orderMsgId, data.result)
        }
        
      })
      await mqtt.subscribe(topic + '/+', 2)
    }else if(workNo == 2) { //卡操作
      const chargeCardService = app.get(ChargeCardService)
      const topic = configService.get('mqtt.topic.chargeSettlement')
      const topicReply = ''
      const mqtt = app.get(MqttService)
      await mqtt.connect()

      mqtt.message((topic, data) => {
        const deviceId = topic.split('/')[1]
        console.log('收到卡充电')
        console.log(data)
        if(data.cardAction == 1) { //查余额
          chargeCardService.balance(data.cardid).then(card => {
            const reply = {
              cmdType : data.cmdType,
              cardAction : data.cardAction,
              packType : 1,
              cardid : data.cardid,
              result : 1,
              remainMoney : 0,
            }
            if(card) {
              if(card.status == 1) {
                reply.remainMoney = Number(card.amount) + Number(card.rewardAmount)
              }else {
                reply.result = 4
              }
            }else {
              reply.result = 2
            }

            mqtt.publish(topicReply, reply)
          })
        }else if(data.cardAction == 2) { //开始充电
          chargeCardService.charge(deviceId, data.outletNum, data.cardid).then(res => {
            mqtt.publish(topicReply, {cmdType : data.cmdType, cardAction : data.cardAction, packType : 1, cardid : data.cardid, ...res})
          })
        }else if(data.cardAction == 3) { //增加充电
          chargeCardService.addCharge(data.orderMsgId).then(res => {
            mqtt.publish(topicReply, {cmdType : data.cmdType, cardAction : data.cardAction, packType : 1, cardid : data.cardid, ...res})
          })
        }else if(data.cardAction == 4) { //停止充电
          mqtt.publish(topicReply, {cmdType : data.cmdType, cardAction : data.cardAction, packType : 1, cardid : data.cardid, result : 1})
        }
      })


      await mqtt.subscribe(topic + '/+', 2)
    }else if(workNo == 3) { //订单上报
      const chargeService = app.get(ChargeService)
      const mqtt = app.get(MqttService)
      await mqtt.connect()

      const topic = configService.get('mqtt.topic.chargeSettlement')
      const topicReply = configService.get('mqtt.topic.chargeSettlementReply')
      mqtt.message((topic, data) => {
        console.log('收到订单结算信息上报结果')
        console.log(data)
        chargeService.settlement(data)
        mqtt.publish(topicReply, {cmdType : data.cmdType, packType : 1, outletNum : data.outletNum, orderMsgId : data.orderMsgId, result : 1})
      })
      await mqtt.subscribe(topic + '/+', 2)
    }else if(workNo == 4) { //
      console.log('------------开启利润分成-----------')
      const profitSettlementService = app.get(ProfitSettlementService)
      const profitSettlementQueue = configService.get('redisKey.profitSettlementQueue') 
      const redis = app.get(RedisService)
      const handler = () => {
        redis.store.rPop(profitSettlementQueue).then(rs => {
          if(rs) {
            const data = JSON.parse(rs)
            profitSettlementService.settlement(data)
          }else {
            setTimeout(() => { //没有消息，5秒后再获取
              handler()
            }, 5000)
          }
        }).catch(() => {
          
        })
      }

      handler()

    }
  }
}
bootstrap();
